home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / unix / c / dirent < prev    next >
Text File  |  1996-11-09  |  5KB  |  291 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/unix/c/RCS/dirent,v $
  4.  * $Date: 1996/10/30 21:59:01 $
  5.  * $Revision: 1.4 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: dirent,v $
  10.  * Revision 1.4  1996/10/30 21:59:01  unixlib
  11.  * Massive changes made by Nick Burret and Peter Burwood.
  12.  *
  13.  * Revision 1.3  1996/09/16 21:23:52  unixlib
  14.  * CL_0002 Nick Burret
  15.  * Minor changes to file handling
  16.  * Change most error numbers, and use in assembler sources (SJC)
  17.  * Various minor bug fixes and compatability changes.
  18.  *
  19.  * Revision 1.2  1996/05/06 09:01:35  unixlib
  20.  * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
  21.  * Saved for 3.7a release.
  22.  *
  23.  * Revision 1.1  1996/04/19 21:35:27  simon
  24.  * Initial revision
  25.  *
  26.  * Jan 1994: Alun Jones, auj@aber.ac.uk
  27.  *
  28.  * As supplied, UnixLib can only hold one directory open.
  29.  * If you try to open two, it returns a valid directory pointer,
  30.  * but overwrites the old version. For example, this stops tar from
  31.  * recursing the directory tree. dirent.c is a fixed version of
  32.  * UnixLib's dirent.
  33.  ***************************************************************************/
  34.  
  35. static const char rcs_id[] = "$Id: dirent,v 1.4 1996/10/30 21:59:01 unixlib Rel $";
  36.  
  37. #include <string.h>
  38. #include <stdlib.h>
  39. #include <unistd.h>
  40.  
  41. #include <sys/unix.h>
  42. #include <sys/syslib.h>
  43. #include <sys/os.h>
  44. #include <sys/types.h>
  45. #include <sys/swis.h>
  46.  
  47. #include <dirent.h>
  48.  
  49. #define DIRBUFSIZ    1024
  50. #define DIRBUFSHIFT    10
  51.  
  52. #define MAXDIRS        32
  53. static struct
  54.   {
  55.     struct dirent *__dirval;
  56.     DIR *which;
  57.   }
  58. dirvals[MAXDIRS];
  59.  
  60. /* opendir() */
  61.  
  62. DIR *
  63. opendir (const char *name)
  64. {
  65.   int i;
  66.   int r[10];
  67.   _kernel_oserror *e;
  68.   register DIR *d;
  69.   char *rname;
  70.  
  71.   rname = __uname ((char *)name, 0);
  72.  
  73.   if (e = os_file (0x05, rname, r))
  74.     {
  75.       __seterr (e);
  76.       return (0);
  77.     }
  78.  
  79.   if (r[0] != 2 && r[0] != 3)    /* pjb, added support for images directories */
  80.     return (0);
  81.  
  82.   if (!(d = malloc (sizeof (DIR))))
  83.     return (0);
  84.   if (!(d->dd_buf = malloc (DIRBUFSIZ)))
  85.     {
  86.       free (d);
  87.       return (0);
  88.     }
  89.   /* We have to store the original format of the name in the
  90.      dirent buffer. The user program might perform some sort of
  91.      hashing and hope that it's copy of the name is the same
  92.      as that of the dirent version.  */
  93.   if (!(d->dd_name = __permstr (name)))
  94.     {
  95.       free (d->dd_buf);
  96.       free (d);
  97.       return (0);
  98.     }
  99.   d->dd_fd = 0;
  100.   d->dd_loc = 0;
  101.   d->dd_size = 0;
  102.   d->dd_bsize = DIRBUFSIZ;
  103.   d->dd_off = 0;
  104.   d->dd_off2 = 0;
  105.  
  106.   for (i = 0; i < MAXDIRS; i++)
  107.     {
  108.       if (!dirvals[i].__dirval)
  109.     {
  110.       if (!(dirvals[i].__dirval = malloc (sizeof (struct dirent))))
  111.         {
  112.           free (d->dd_name);
  113.           free (d->dd_buf);
  114.           free (d);
  115.           return (0);
  116.         }
  117.       dirvals[i].which = d;
  118.       break;
  119.     }
  120.     }
  121.  
  122.   return (d);
  123. }
  124.  
  125. /* __nextdir() */
  126.  
  127. static int
  128. __nextdir (register DIR * d)
  129. {
  130.   int r[10];
  131.   _kernel_oserror *e;
  132.   register int i;
  133.   register char *s;
  134.   char *rname;
  135.  
  136.   if (d->dd_off2 < 0)
  137.     return (-1);
  138.  
  139.   /* Got to convert the filename on every usage since it could
  140.      be Unix format.  */
  141.   rname = __uname (d->dd_name, 0);
  142.   r[0] = 9;
  143.   r[1] = (int) rname;
  144.   r[2] = (int) d->dd_buf;
  145.   r[3] = DIRBUFSIZ / MAXNAMLEN;
  146.   r[4] = d->dd_off2;
  147.   r[5] = DIRBUFSIZ;
  148.   r[6] = (int) "*";
  149.  
  150.   if (e = os_swi (OS_GBPB, r))
  151.     {
  152.       __seterr (e);
  153.       free (d->dd_name);
  154.       free (d->dd_buf);
  155.       free (d);
  156.       return (-1);
  157.     }
  158.  
  159.   for (i = r[3], s = d->dd_buf; i; i--)
  160.     while (*++s);
  161.  
  162.   d->dd_loc = 0;
  163.   d->dd_size = s - d->dd_buf;
  164.   d->dd_off = (d->dd_off2 << DIRBUFSHIFT);
  165.   d->dd_off2 = r[4];
  166.  
  167.   if (r[4] < 0 && !r[3])
  168.     return (-1);
  169.  
  170.   return (0);
  171. }
  172.  
  173. /* readdir() */
  174.  
  175. struct dirent *
  176. readdir (d)
  177.      register DIR *d;
  178. {
  179.   register struct dirent *r = NULL;
  180.   register int i;
  181.   register char *s;
  182.  
  183.   if (!d)
  184.     return (0);
  185.  
  186.   for (i = 0; i < MAXDIRS; i++)
  187.     {
  188.       if ((dirvals[i].__dirval) && (dirvals[i].which == d))
  189.     {
  190.       r = dirvals[i].__dirval;
  191.       break;
  192.     }
  193.     }
  194.  
  195.  
  196.   if (!r)
  197.     return (0);
  198.  
  199.   while (d->dd_loc >= d->dd_size)
  200.     if (__nextdir (d))
  201.       return (0);
  202.  
  203.   s = d->dd_buf + d->dd_loc;
  204.   i = strlen (s);
  205.   r->d_off = d->dd_off;
  206.   i++;
  207.   d->dd_off += i;
  208.   d->dd_loc += i;
  209.   if (i >= MAXNAMLEN)
  210.     s[i = MAXNAMLEN - 1] = 0;
  211.   memcpy (r->d_name, s, i);
  212.   r->d_namlen = i;
  213.   r->d_reclen = DIRSIZ (r);
  214.  
  215.   /* The file serial number. This is the same as the st_ino member
  216.      that stat will return for the file.  */
  217.   r->d_fileno = __get_file_serial_no (r->d_name);
  218.  
  219.   return (r);
  220. }
  221.  
  222. /* telldir() */
  223.  
  224. long
  225. telldir (d)
  226.      DIR *d;
  227. {
  228.   if (!d)
  229.     return (-1);
  230.  
  231.   return (d->dd_off);
  232. }
  233.  
  234. /* seekdir() */
  235.  
  236. void
  237. seekdir (d, off)
  238.      DIR *d;
  239.      long off;
  240. {
  241.   if (!d)
  242.     return;
  243.  
  244.   if (d->dd_off2 != (off >> DIRBUFSHIFT))
  245.     {
  246.       d->dd_off2 = (((int) off) >> DIRBUFSHIFT);
  247.       d->dd_loc = 0;
  248.       d->dd_size = 0;
  249.       __nextdir (d);
  250.     }
  251.  
  252.   d->dd_off = (size_t) off;
  253.   d->dd_loc = (size_t) off & (DIRBUFSHIFT - 1);
  254. }
  255.  
  256. /* rewinddir() */
  257.  
  258. void (rewinddir) (d)
  259.      DIR *d;
  260. {
  261.   rewinddir (d);
  262. }
  263.  
  264. /* closedir() */
  265.  
  266. int
  267. closedir (d)
  268.      DIR *d;
  269. {
  270.   int i;
  271.   if (!d)
  272.     return (-1);
  273.  
  274.   for (i = 0; i < MAXDIRS; i++)
  275.     {
  276.       if (dirvals[i].__dirval && (dirvals[i].which == d))
  277.     {
  278.       free (dirvals[i].__dirval);
  279.       dirvals[i].__dirval = 0;
  280.       dirvals[i].which = 0;
  281.       break;
  282.     }
  283.     }
  284.  
  285.   free (d->dd_name);
  286.   free (d->dd_buf);
  287.   free (d);
  288.  
  289.   return (0);
  290. }
  291.